import json
import os
from typing import List, Tuple, Any

import lib.utils.log_loader as log_loader


class ChatQuestionAnswer:
    def __init__(self, question: str, answer: str, md5: str, data_message_id: Any):
        self.question = question
        self.answer = answer
        self.md5 = md5
        self.data_message_id = data_message_id

    def to_dict(self) -> dict:
        """将ChatQuestionAnswer对象转化为字典"""
        return {
            "question": self.question,
            "answer": self.answer,
            "md5": self.md5,
            "data_message_id": self.data_message_id
        }

    @classmethod
    def from_dict(cls, data: dict):
        """从字典中还原为ChatQuestionAnswer对象"""
        return cls(data["question"], data["answer"], data["md5"], data["data_message_id"])


def save_chat_log(chat_log, file_path: str):
    """保存聊天记录到JSON文件"""
    chat_log_dicts = [cqo.to_dict() for cqo in chat_log]
    with open(file_path, "w", encoding="utf-8") as f:  # 在这里指定编码
        json.dump(chat_log_dicts, f, ensure_ascii=False, indent=4)


def record_exists(loaded_chat_log, new_data_message_id):
    """
    检查给定的聊天记录中是否已经存在指定的消息记录。

    参数:
    loaded_chat_log - 一个包含聊天记录的列表，每个聊天记录是一个对象，其中必须包含data_message_id属性。
    new_data_message_id - 需要检查是否存在的消息记录的ID。

    返回值:
    返回一个布尔值，如果聊天记录中已经存在指定ID的消息记录，则为True；否则为False。
    """
    return any(cqo.data_message_id == new_data_message_id for cqo in loaded_chat_log)

    # 使用生成器表达式遍历 loaded_chat_log 中的每个记录，检查是否存在data_message_id与new_data_message_id相等的记录。


def record_md5_exists(loaded_chat_log, new_md5):
    return any(cqo.md5 == new_md5 for cqo in loaded_chat_log)


def add_chat_log(new_chat_record: ChatQuestionAnswer, file_name: str):
    """
    向JSON文件中添加聊天记录。

    参数:
    new_chat_record: ChatQuestionAnswer 类型，代表一条新的聊天记录。

    file_name: str 类型，指定要添加聊天记录的JSON文件名称。

    返回值:
    返回 True 表示聊天记录成功添加或更新，返回 False 表示聊天记录已存在且无需更新。
    """
    logger = log_loader.get_logger()  # 获取日志记录器
    message_path = get_message_path(file_name)  # 获取聊天记录文件的路径

    # 加载现有的聊天记录
    chat_log_list = load_chat_log(message_path)
    if chat_log_list is None:
        # 如果聊天记录为空，则直接保存新记录
        logger.debug(f"保存消息：{new_chat_record.question[:20]}")
        save_chat_log([new_chat_record], message_path)
        return True
    else:
        # 遍历聊天记录，查找是否存在相同 data_message_id 的记录
        for i, record in enumerate(chat_log_list):
            if record.data_message_id == new_chat_record.data_message_id:
                if record.md5 != new_chat_record.md5:
                    # 如果找到相同 data_message_id 但 md5 不同的记录，则进行更新
                    chat_log_list[i] = new_chat_record
                    save_chat_log(chat_log_list, message_path)
                    logger.debug(f"更新消息：{new_chat_record.question[:20]}")
                    return True
                else:
                    # 如果找到相同 data_message_id 且 md5 也相同的记录，则不进行更新
                    return False
        # 如果没有找到相同 data_message_id 的记录，则将新记录添加到列表中
        chat_log_list.append(new_chat_record)
        save_chat_log(chat_log_list, message_path)
        logger.debug(f"保存消息：{new_chat_record.question[:20]}")
        return True


def load_chat_log(file_name: str) -> List[ChatQuestionAnswer] | None:
    """从JSON文件中加载聊天记录"""
    message_path = get_message_path(file_name)

    if not os.path.exists(message_path) or not os.path.isfile(message_path):
        return None

    with open(message_path, "r", encoding="utf-8") as f:
        chat_log_dicts = json.load(f)
    return [ChatQuestionAnswer.from_dict(data) for data in chat_log_dicts]


def find_answer_by_question(file_name: str, data_message_id: str) -> tuple[str, str, str, Any] | tuple[
    None, None, None, None]:
    """根据问题查找对应的回答"""
    loaded_chat_log = load_chat_log(file_name)

    for cqo in loaded_chat_log:
        if cqo.data_message_id == data_message_id:
            return cqo.question, cqo.answer, cqo.md5, cqo.data_message_id
    return None, None, None, None


def get_message_path(file_name: str) -> str:
    """
    获取消息文件路径

    参数:
    file_name: str - 配置文件的名称

    返回值:
    str - 消息文件的完整路径
    """
    # 定义消息文件存储的基础目录
    message_dir = 'message'
    # 规范化路径，确保可以正确处理相对路径中的上层目录引用
    message_dir = os.path.normpath(message_dir)

    # 获取去除路径部分后剩余的文件名，以确保配置文件名的安全性
    safe_config_name = os.path.basename(file_name)
    # 拼接消息文件的完整路径
    message_path = os.path.join(message_dir, safe_config_name)

    return message_path


# 示例用法
if __name__ == "__main__":

    add_chat_log(ChatQuestionAnswer("你叫什么名字?", "我是ChatBot，你的智能助手。", "bot", "123456"), "chat_log.json")
    add_chat_log(
        ChatQuestionAnswer("今天的天气如何?", "我无法直接查询实时天气，请访问相关网站或使用专业天气应用获取信息。", "bot",
                           "123547"), "chat_log.json")
    add_chat_log(ChatQuestionAnswer("你叫什么名字?", "我是ChatBot，你的智能助手。", "bot", "123456"), "chat_log.json")
    add_chat_log(ChatQuestionAnswer("你能帮我查个单词吗?", "当然可以，请告诉我你要查询的单词。", "bot", "5745421"),
                 "chat_log.json")

    # loaded_chat_log = load_chat_log("chat_log.json")

    id = "123456"
    question, answer, role, data_message_id = find_answer_by_question("chat_log.json", id)
    if answer:
        print(f"问题: {question}")
        print(f"回答: {answer}")
        print(f"角色: {role}")
        print(f"属性一: {data_message_id}")
    else:
        print(f"未找到与问题'{id}'匹配的回答。")
